北邮操作系统实验三文件系统和设备管理LJ.docx |
您所在的位置:网站首页 › linux 设备管理 › 北邮操作系统实验三文件系统和设备管理LJ.docx |
北邮操作系统实验三文件系统和设备管理LJ.docx 《北邮操作系统实验三文件系统和设备管理LJ.docx》由会员分享,可在线阅读,更多相关《北邮操作系统实验三文件系统和设备管理LJ.docx(12页珍藏版)》请在冰豆网上搜索。 北邮操作系统实验三文件系统和设备管理LJ 操作系统 实验三文件系统和设备管理 作者: 北邮 班级 2009211309 学院(系): 计算机学院 专业: 指导教师: 分数: 目录 1.实验目的2 2.实验要求2 3.具体实现2 3.1.LINUX下串口的非阻塞读写程序……2 3.2.模块……3 3.3实现一个procfs文件系统的模块…………………………7 4.实验心得…………………………………………………………… 5.附录源代码9 1. 实验目的 了解LINUX下文件系统和I/O的实现,了解其中模块的设计。
2.项目要求 (a)实现一个LINUX下串口的非阻塞读写程序。 (b)了解LINUX下模块的实现方式,及相应的编译和安装及卸载过程。 实现一个模块,在模块安装时可打印信息(Hello)和卸载时打印信息(Goodbye). (c)实现一个procfs文件系统的模块。
3.具体实现 3.1LINUX下串口的非阻塞读写程序 在Linux下串口文件是位于/dev下,串口一为/dev/ttyS0,串口二为/dev/ttyS1打开串口是通过使用标准的文件打开函数操作: intfd; /*以读写方式打开串口*/ fd=open("/dev/ttyS0",O_RDWR); if(-1==fd){ /*不能打开串口一*/ perror("提示错误! "); } 在使用时还应当设置串口、读写串口、关闭串口等,通过查阅资料实现了对串口的读写 代码见附录 3.2模块 模块是具有独立功能的程序,它可以被单独编译,但不能独立运行。 它在运行时被链接到内核作为内核的一部分在内核空间运行,这与运行在用户空间的进程是不同的。 模块通常由一组函数和数据结构组成,用来实现一种文件系统、一个驱动程序或其他内核上层的功能。 首先在电脑里编写一段C语言代码,hello.c。 代码如下 分析: (1)在内核模块的开始一部分,跟C语言的一般程序一样,是模块所需要的头文件。 (2)模块许可证声明,这部分是必须有的。 模块许可证(LICENSE)声明描述内核模块的许可权限,如果不声明LICENSE,模块被加载时,将收到内核被污染(kerneltainted)的警告。 大多数情况下,内核模块应遵守GPL兼容许可权。 Linux2.6内核模块最常见的是以MODULE_LICENSE("DualBSD/GPL")语句声明模块采用BSD/GPL双LICENSE。 (3)模块加载函数,这部分是必须的。 模块加载函数必须“module_init(函数名)“的形式被指定。 它返回整形值,若初始化成功,应返回0。 在上面那个例子当中,hello_init()函数就是模块加载函数需要执行的,主要是打印一条信息。 (4)跟模块加载函数相对应的就是模块卸载函数,这部分也是必须的。 模块卸载函数在模块卸载的时候执行,不返回任何值,必须以“module_exit(函数名)“的形式来指定。 在上面的例子中,hello_exit()函数就是模块卸载函数需要执行的,只要是打印了一条退出信息。 (5)函数最后的一部分,是模块声明与描述部分。 这部分可有可无。 在Linux内核模块中,我们可以用 MODULE_AUTHOR,MODULE_DESCRIPTION,MODULE_VERSION,MODULE_DEVICE_TABLE,MODULE_ALIAS分别声明模块的作者、描述、版本、设备表和别名。 (6)module_init()是驱动程序初始化的入口点。 它就相当于c语言程序中的main()函数。 对于内置的模块,内核在引导时调用该引导点,对于可加载模块则在模块插入到内核时才调用。 (7)模块加载函数和模块卸载函数中都用到了printk()函数,该函数是由内核定义的,功能与C库中的printf()类似,它把要打印的信息输出到终端或系统日志中。
其次,编写Makefile文件,通过它来管理一个庞大的项目是再好不过的。 下面我们就在刚才.c文件目录下编写一个Makefile文件。 对应的代码如下: pwd是获得当前的相对路径,然后就是获得当前的内核版本号,我们可以用uname-r命令,这样我们就获得了当前内核的绝对路径。 这样做的一个好处,就是你可以在不同的内核版本中进行移植,而且可读性也增强了。 有了Makefile文件后,就离成功不远了。 在.c文件的同一目录下,执行make命令,系统会在当前目录下生成各种文件。 其中就有与之相关的.o和.ko文件。 hello.ko就是模块目标文件。 到此,模块编译好了。 截图如下:
模块编译好了,但是还不能为我们工作。 下面就是将目标模块插入到内核和从内核中删除。 这里需要用到两个命令,insmod和rmmod我们光看这两个命令单词就能猜出他们的意思。 输入命令: sudoinsmodhello.ko。 要看信息必须要进入到日志文件中,可输入命令进到系统日志: dmesg,会发现有一条信息,HelloWorld,说明我们刚才编写的模块已经插入到内核当中了。 接下来输入命令: sudormmodhello.ko。 再输入命令打开系统日志,我们会发现在会有一个新的信息Goodbye,这说明我们的模块卸载成功。 至此,实现一个模块,在模块安装时可打印信息(Helloworld)和卸载时打印信息(Goodbye)完成 3.3实现一个procfs文件系统的模块 /proc文件系统是在LINUX系统中的一个特殊部分,它并不属于任何应用的文件系统,它的主要作用是用于用户与系统的参数交换,但使用更多的是通过/proc系统中的文件内容来查看系统当前运行状态。 程序中主要是要靠调用LINUX提供的系统函数来创建表项和文件夹,并且通过修改读写函数的指针,可以实现对于该文件读写的重调用。 其中,建立文件和文件夹的函数是: staticstructproc_dir_entry*mydir; staticstructproc_dir_entry*pfile; staticintmyproc_write(structfile*,constchar__user*, unsignedlong,void*) staticintmyproc_read(char*,char**,off_t, int,int*,void*) 编写Makefile文件,和上面的类似,这里就不过多赘述。 编写编译procfc_模块,: 生成如下文件: 在/procfc_os中创建mydir文件夹
4实验心得 (a)在实验中初步学习了LINUX串口编程,了解了各个函数的功能。 因为硬件的关系,故只是模拟了串口的写入及读出。 实际中应该将两个串口相连来实现 (b)本次实验中亲自动手实践了LINUX内核的模块编程,并初步了解了内核模块在LINUX内核中的位置和运行方式。 加强了对linux模块的了解 (c)本次实验中结合内核模块的编程方式,通过上网查找资料及去图书馆借阅书籍,学会写PROC文件系统的文件。 5附录(3.1及3.3的原程序) 5.1 #include #include #include #include #include intmain() { intfd,flag,wr_num=0,rd_num=0; charsend_buf[512],recv_buf[512]; while (1) { fd=open("/dev/minttyS0",O_RDWR|O_NOCTTY|O_NDELAY); if(fd==-1) printf("cannotopentheCOM1! \n"); else { fcntl(fd,F_SETFL,0); printf("openInput-serialportsuccessfully! \n"); printf("Input: \n"); scanf("%s",send_buf); wr_num=write(fd,send_buf,sizeof(send_buf));/*先写入*/ if(wr_num>0) printf("writesuccess! \n\n"); else printf("writefail! \n\n"); sleep (1); } close(fd); fd=open("/dev/minttyS0",O_RDWR|O_NOCTTY|O_NDELAY); if(fd==-1) printf("cannotopentheCOM2! \n"); else { fcntl(fd,F_SETFL,0); printf("openOutput-serialportsuccessfully! \n"); rd_num=read(fd,recv_buf,sizeof(recv_buf));/*再读出*/ if(rd_num>0) { recv_buf[rd_num]='\0'; printf("wecanread\"%s\"fromtheCOM1.total: %dcharacters\n\n",recv_buf,rd_num); } else printf("readfail! \n"); sleep (2); } close(fd); } } 5.2 #include #include #include staticstructproc_dir_entry*mydir; staticstructproc_dir_entry*pfile; staticcharmsg[255]; staticintmyproc_read(char*page,char**start,off_toff,intcount,int*eof,void*data) { intlen=strlen(msg); if(off>=len) return0; if(count>len-off) count=len-off; memcpy(page+off,msg+off,count); returnoff+count; } staticintmyproc_write(structfile*file,constchar__user*buffer,unsignedlongcount,void*data) { unsignedlongcount2=count; if(count2>=sizeof(msg)) count2=sizeof(msg)-1; if(copy_from_user(msg,buffer,count2)) return-EFAULT; msg[count2]='\0'; returncount; } staticint__initmyproc_init(void) { mydir=proc_mkdir("mydir",NULL); if(! mydir){ printk(KERN_ERR"Can'tcreate/procfc_os/mydir\n"); return-1; } pfile=create_proc_entry("Pool",0666,mydir); if(! pfile){ printk(KERN_ERR"Can'tcreate/procfc_os/mydir/pool\n"); remove_proc_entry("mydir",NULL); return-1; } pfile->read_proc=myproc_read; pfile->write_proc=myproc_write; return0; } staticvoid__exitmyproc_exit(void) { remove_proc_entry("pool",mydir); remove_proc_entry("mydir",NULL); }
|
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |